﻿using Magellan.Framework;

namespace Magellan.Routing
{
    /// <summary>
    /// A <see cref="IRouteHandler"/> for Model-View-Controller routes.
    /// </summary>
    public class ControllerRouteHandler : IRouteHandler
    {
        private readonly IControllerFactory _controllerFactory;
        private readonly ViewEngineCollection _viewEngines;

        /// <summary>
        /// Initializes a new instance of the <see cref="ControllerRouteHandler"/> class.
        /// </summary>
        /// <param name="controllerFactory">The controller factory.</param>
        public ControllerRouteHandler(IControllerFactory controllerFactory) : this(controllerFactory, null)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ControllerRouteHandler"/> class.
        /// </summary>
        /// <param name="controllerFactory">The controller factory.</param>
        /// <param name="viewEngines">The view engines.</param>
        public ControllerRouteHandler(IControllerFactory controllerFactory, ViewEngineCollection viewEngines)
        {
            _controllerFactory = controllerFactory;
            _viewEngines = viewEngines ?? ViewEngines.CreateDefaults();
        }

        /// <summary>
        /// Processes the navigation request.
        /// </summary>
        /// <param name="request">The navigation request information.</param>
        public void ProcessRequest(NavigationRequest request)
        {
            var controllerName = request.RouteValues.GetOrDefault<string>("controller");
            
            request.ReportProgress(new BeginRequestNavigationEvent());
            request.ReportProgress(new ResolvingControllerNavigationEvent());
            var controllerLease = _controllerFactory.CreateController(request, controllerName);
            var controller = controllerLease.Controller;
            controller.Execute(
                new ControllerContext(
                    controllerLease.Controller, 
                    request, 
                    _viewEngines,
                    () =>
                        {
                            controllerLease.Dispose();
                            request.ReportProgress(new CompleteNavigationEvent());
                        }));
        }
    }
}
